package org.ejde.sciencelogs;

import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;

import org.w3c.dom.Document;
import org.w3c.dom.Element;

/**
 * This class contains the attributes and behaviors for formfields. Formfields
 * are generic containers for storing all information needed to create the Java
 * Swing objects used to select and customized events for submission to the
 * eventlog.
 * 
 * This class also includes the methods for creating Java Swing Components based
 * on the information in the formField objects.
 * 
 * @author Eric Martin
 * @version 0.1
 */
public class formField {

	/**
	 * Field Type enumeration table. Used to specify the Swing input widget type
	 * to use for the field
	 */
	public static final short TEXT_FIELD = 1;
	public static final short LIST_FIELD = 2;
	public static final short TEXTAREA_FIELD = 3;
	public static final short CHECK_FIELD = 4;

	/**
	 * The input widget type of the formfield object
	 */
	public short type;

	// Because the input widget type is unknown at compile
	// time, formField object must include a pointed to
	// all possible input widget types.
	/**
	 * The pointer to a JTextField object
	 */
	private JTextField textfield;

	/**
	 * The pointer to a JComboBox object
	 */
	private JComboBox listfield;

	/**
	 * The pointer to a JTextArea object
	 */
	private JTextArea textarea;

	/**
	 * The pointer to a JScrollPane object
	 */
	private JScrollPane scrollpane;

	
	// formField Properties
	/**
	 * The text to display in a text field or textarea object.
	 */
	private String text = "";

	/**
	 * Boolean flag to determine if the text should be preceeded by the head
	 * text
	 */
	private boolean hdrout = false;

	/**
	 * The header text
	 */
	private String header = "";

	/**
	 * Boolean flag to determine if the text should be cleared after the event
	 * is submitted.
	 */
	private boolean clearonsubmit = true;

	
	/**
	 * The text to display in tooltip.
	 */
	private String tooltip = "";

	
	// Objects related to the formField's label
	/**
	 * The JLabel object
	 */
	private JLabel labelobj;

	/**
	 * The text of the JLabel
	 */
	private String label;

	/**
	 * The JLabel potions
	 */
	private String[] options;

	// Location identifier fields
	/**
	 * The panel ID
	 */
	public int panelID;

	/**
	 * The subpanel ID
	 */
	public int subpanelID;

	/**
	 * The unique field ID
	 */
	public int fieldID;

	/**
	 * Constructor method. Creates basic formField object based on a widget
	 * type, field name and field header name.
	 * 
	 * @param typeselect
	 *            the widget type
	 * @param labelpass
	 *            the field label
	 * @param shortname
	 *            the field header name
	 */
	public formField(short typeselect, String labelpass, String shortname) {
		this.type = typeselect;
		this.label = labelpass;
		this.header = shortname.toUpperCase().replace(" ", "_");

	}

	/**
	 * Constructor method. Creates basic formField object based on a widget
	 * type, field name and field header name.
	 * 
	 * @param typeselect
	 *            the widget type
	 * @param labelpass
	 *            the field label
	 * @param shortname
	 *            the field header name
	 * @param optionspass
	 *            the field label options
	 */
	public formField(short typeselect, String labelpass, String shortname,
			String[] optionspass) {
		this.type = typeselect;
		this.label = labelpass;
		this.options = optionspass;
		this.header = shortname.toUpperCase().replace(" ", "_");
	}

	/**
	 * Constructor method. Creates a blank textfield formfield object
	 */
	public formField() {
		type = TEXT_FIELD;
	}

	/**
	 * Set method. Sets the widget type for the formfield
	 * 
	 * @param typeselect
	 */
	public void setType(short typeselect) {
		this.type = typeselect;
	}

	/**
	 * Set method. Sets the panel ID, subpanel ID and field ID for each
	 * formField object
	 * 
	 * @param panel
	 *            the panel ID to set for the object.
	 * @param subpanel
	 *            the subpanel ID to set for the object.
	 * @param field
	 *            the field ID to set for the object.
	 */
	public void setID(int panel, int subpanel, int field) {
		this.panelID = panel;
		this.subpanelID = subpanel;
		this.fieldID = field;
	}

	/**
	 * Set the label text for the formField object
	 * 
	 * @param labelselect
	 *            the label text to apply
	 */
	public void setLabel(String labelselect) {
		this.label = labelselect;
		// Added to convert for use in header output;
		// this.header = this.label.trim().toUpperCase().replace(" ","_");
	}

	/**
	 * Set the header text for the formField object
	 * 
	 * @param shortname
	 *            the header text to apply
	 */
	public void setHeader(String shortname) {
		this.header = shortname.toUpperCase().replace(" ", "_");
	}

	/**
	 * Set the boolean flag for whether to include the header text when writing
	 * the event text to the logfile.
	 * 
	 * @param flag
	 *            boolean flag. True = add header text to event.
	 */
	public void setHdrout(boolean flag) {
		this.hdrout = flag;
	}

	/**
	 * Set the boolean flag for whether to clear the text field after submitting
	 * the event.
	 * 
	 * @param flag
	 *            boolean flag. True = clear after submit
	 */
	public void setClearOnSubmit(boolean flag) {
		this.clearonsubmit = flag;
	}

	/**
	 * Set the JLabel options
	 * 
	 * @param optionselect
	 *            the JLabel options
	 */
	public void setOptions(String[] optionselect) {
		this.options = optionselect;
	}

	/**
	 * Set the text of input widget.
	 * 
	 * @param text
	 *            String contain the text
	 */
	public void setText(String text) {
		this.text = text;
	}

	/**
	 * Set the widget type for the formField object.
	 * 
	 * @param tooltip
	 *            the formField widget type.
	 */
	public void setToolTip(String tooltip) {
		this.tooltip = tooltip;
	}

	/**
	 * Create the JLabel and input widget based on the formField object.
	 */
	public void create() {
		this.labelobj = new JLabel(this.label + ":");
		this.labelobj.setHorizontalAlignment(JLabel.RIGHT);
		// System.out.println("creating label: "+this.label+":");
		switch (this.type) {
		case TEXT_FIELD:
			createTextField();
			break;
		case LIST_FIELD:
			createListField();
			break;
		case TEXTAREA_FIELD:
			createTextAreaField();
			break;
		}
	}

	/**
	 * Create a JTextField widget. Called in the create() method.
	 */
	private void createTextField() {
		// Create JTextField object.
		this.textfield = new JTextField(this.text, 8);

		// Add tooltip, if available.
		if(this.tooltip != null) {
			this.textfield.setToolTipText(this.tooltip);
		}

	}

	/**
	 * Create a JComboBox widget. Called in the create() method.
	 */
	private void createListField() {
		//If the formField object has options, create the JComboBox object
		if (this.options != null) {
			this.listfield = new JComboBox(this.options);

			// Make this an attribute option.
			this.listfield.setEditable(true);

			// Add tooltip, if available.
			if(this.tooltip != null) {
				this.listfield.setToolTipText(this.tooltip);
			}
		}
	}

	/**
	 * Create a JTextArea widget. Called in the create() method.
	 */
	private void createTextAreaField() {
		// Create JTextArea object
		this.textarea = new JTextArea(5, 60);
		this.scrollpane = new JScrollPane(textarea);

		// Add tooltip, if available.
		if(this.tooltip != null) {
			this.textarea.setToolTipText(this.tooltip);
		}

	}

	// Get Methods

	/**
	 * Get Method. Returns the JLabel object.
	 * 
	 * @return the JLabel object.
	 */
	public JLabel getLabel() {
		return this.labelobj;
	}

	/**
	 * Get Method. Returns the JTextfield object.
	 * 
	 * @return the JTextField object.
	 */
	public JTextField getTextField() {
		return this.textfield;
	}

	/**
	 * Get Method. Returns the JComboBox object.
	 * 
	 * @return the JComboBox object.
	 */
	public JComboBox getListField() {
		return this.listfield;
	}

	/**
	 * Get Method. Returns the JScrollPane object.
	 * 
	 * @return the JScrollPane object.
	 */
	public JScrollPane getTextAreaField() {
		// return this.textareafield;
		return this.scrollpane;
	}

	/**
	 * Get Method. Returns the text from the input object as plain text.
	 * 
	 * @return the text as a String in plain text.
	 */
	public String getValue() {
		String out = "no_value";
		switch (this.type) {
		case TEXT_FIELD:
			out = this.textfield.getText().trim().replace(" ", "_");
			break;
		case LIST_FIELD:
			out = (String) this.listfield.getSelectedItem();
			if (out != null) {
				out = out.trim().replace(" ", "_");
			} else {
				out = "";
			}
			break;
		case TEXTAREA_FIELD:
			// out =this.textareafield.getText();
			out = this.textarea.getText().trim().replace("\r", "|")
					.replace("\n", " | ").replace(" ", "_");

			break;
		}
		if (out.equals("")) {
			out = "NaN";
		}
		if (this.hdrout == true) {
			out = this.header + ":" + out;
		}
		return out;
	}

	/**
	 * Get Method. Returns the text from the input object as XML.
	 * 
	 * @return the text as a String in XML.
	 */
	public String getXMLValue() {
		String out = "no_value";
		switch (this.type) {
		case TEXT_FIELD:
			out = this.textfield.getText().trim().replace(" ", "_");
			break;
		case LIST_FIELD:
			out = (String) this.listfield.getSelectedItem();
			if (out != null) {
				out = out.trim().replace(" ", "_");
			} else {
				out = "";
			}
			break;
		case TEXTAREA_FIELD:
			// out =this.textareafield.getText();
			out = this.textarea.getText().trim().replace("\r", "|")
					.replace("\n", " | ").replace(" ", "_");

			break;
		}
		if (out.equals("")) {
			out = "NaN";
		}

		return out;
	}

	/**
	 * toXML()
	 * 
	 * @return an xml dom node for insertion into an entry element
	 */
	public Element toElement(Document doc) {

		String xmllabel = label.trim().replaceAll("[^a-zA-Z0-9_.]+", "-")
				.replaceAll(" ", "-").toLowerCase();
		if (xmllabel.charAt(xmllabel.length() - 1) == '-') {
			xmllabel = xmllabel.substring(0, xmllabel.length() - 2);
		}

		Element outnode = doc.createElement(xmllabel);

		String out = "no_value";
		switch (this.type) {
		case TEXT_FIELD:
			// outnode.setAttribute("value", (this.textfield.getText().trim()));
			outnode.appendChild(doc.createTextNode((this.textfield.getText()
					.trim())));

			break;

		case LIST_FIELD:
			out = (String) this.listfield.getSelectedItem();
			if (out != null) {
				// outnode.setAttribute("value",(out));
				outnode.appendChild(doc.createTextNode((out.trim())));

			} else {
				// outnode.setAttribute("value", "");
				outnode.appendChild(doc.createTextNode(""));
			}
			break;

		case TEXTAREA_FIELD:
			outnode.appendChild(doc.createTextNode((this.textarea.getText()
					.trim())));
			break;
		}

		return outnode;
	}

	/**
	 * Clear the text in the formField objects based on the clearonsubmit
	 * boolean flag.
	 */
	public void checkAndClear() {
		if (this.clearonsubmit) {
			switch (this.type) {
			case TEXT_FIELD:
				this.textfield.setText("");
				break;
			case LIST_FIELD:
				this.listfield.setSelectedIndex(0);
				break;
			case TEXTAREA_FIELD:
				this.textarea.setText("");
				break;
			}

		}
	}

	/**
	 * Get method. Returns the header text
	 * 
	 * @return the header text as a string
	 */
	public String getHeader() {
		return header;
	}

	/**
	 * Get method. Returns the label text
	 * 
	 * @return the label text as a string
	 */
	public String getLabelString() {
		return label;
	}
}
